package rpc

import (
	"context"
	"fmt"
	"net"

	"frigate/internal/raftnode"
	"frigate/utils"

	"github.com/hashicorp/raft"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"

	pb "frigate/internal/proto"
)

type ClusterServer struct {
	pb.UnimplementedClusterServiceServer
	raftNode *raftnode.Node
}

func NewClusterServer(raftNode *raftnode.Node) *ClusterServer {
	return &ClusterServer{raftNode: raftNode}
}

// Join 实现：接收新节点加入请求，并通过 Raft 接口添加到集群
func (s *ClusterServer) Join(ctx context.Context, req *pb.JoinRequest) (*pb.JoinResponse, error) {
	utils.Logger.Info().Msg(fmt.Sprint("Received join request: node_id=%s, raft_addr=%s", req.NodeId, req.RaftAddr))
	configFuture := s.raftNode.Raft.GetConfiguration()
	if err := configFuture.Error(); err != nil {
		return &pb.JoinResponse{Success: false, Message: err.Error()}, nil
	}

	// 检查是否已存在
	for _, srv := range configFuture.Configuration().Servers {
		if srv.ID == raft.ServerID(req.NodeId) {
			return &pb.JoinResponse{Success: true, Message: "node already in cluster"}, nil
		}
	}

	// 添加新节点（异步）
	future := s.raftNode.Raft.AddVoter(
		raft.ServerID(req.NodeId),
		raft.ServerAddress(req.RaftAddr),
		0, 0,
	)
	if err := future.Error(); err != nil {
		return &pb.JoinResponse{Success: false, Message: err.Error()}, nil
	}

	return &pb.JoinResponse{
		Success: true,
		Message: "node added successfully",
	}, nil
}

// Status 返回当前节点状态
func (s *ClusterServer) Status(ctx context.Context, req *pb.StatusRequest) (*pb.StatusResponse, error) {
	var role string
	// 修复: 检查节点状态是否为Leader
	isLeader := s.raftNode.Raft.State() == raft.Leader

	switch s.raftNode.Raft.State() {
	case raft.Leader:
		role = "leader"
	case raft.Follower:
		role = "follower"
	case raft.Candidate:
		role = "candidate"
	default:
		role = "unknown"
	}

	// 获取当前成员列表
	configFuture := s.raftNode.Raft.GetConfiguration()
	if err := configFuture.Error(); err != nil {
		return &pb.StatusResponse{
			NodeId:   string(s.raftNode.Config.LocalID),
			Role:     role,
			IsLeader: isLeader,
			Peers:    []string{},
		}, nil
	}

	var peers []string
	for _, srv := range configFuture.Configuration().Servers {
		peers = append(peers, string(srv.ID))
	}

	return &pb.StatusResponse{
		NodeId:   string(s.raftNode.Config.LocalID),
		Role:     role,
		IsLeader: isLeader,
		Peers:    peers,
	}, nil
}

// Start 启动 gRPC 服务
func (s *ClusterServer) Start(address string) error {
	lis, err := net.Listen("tcp", address)
	if err != nil {
		return err
	}

	grpcServer := grpc.NewServer()
	pb.RegisterClusterServiceServer(grpcServer, s)
	reflection.Register(grpcServer) // 支持 gRPC CLI 工具调试

	utils.Logger.Info().Msg(fmt.Sprintf("gRPC server listening on %s", address))
	return grpcServer.Serve(lis)
}
